package com.bjc.platform.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bjc.platform.Constants;
import com.bjc.platform.dao.GenericDao;
import com.bjc.platform.model.AdmOrg;
import com.bjc.platform.model.CustomUserDetails;
import com.bjc.platform.repository.AdmOrgRepo;
import com.bjc.platform.service.AdmOrgService;
import com.bjc.platform.util.Page;
import com.bjc.platform.util.SqlUtil;
import com.bjc.platform.util.StaticMethod;
import com.bjc.platform.vo.AdmOrgSearchCondition;
import com.bjc.platform.vo.ExtTreeModel;

@Service
public class AdmOrgServiceImpl implements AdmOrgService {

	@Autowired
	GenericDao genericDao;
	@Autowired
	private AdmOrgRepo admOrgRepo;

	@Override
	public List<AdmOrg> getAll() {
		Iterable<AdmOrg> it = admOrgRepo.findAll();
		List<AdmOrg> orgs = new ArrayList<AdmOrg>();
		if (it != null) {
			for (Iterator<AdmOrg> itr = it.iterator(); itr.hasNext();) {
				orgs.add(itr.next());
			}
		}
		return orgs;
	}

	@Override
	public AdmOrg save(AdmOrg org, String parentOrgType) {
		// 如果是新增就要设置组织的类型为父组织类型的子类型
		if (org != null && org.getId() == null) {
			org.setOrgnizeType(OrgTypeEnum.getSubOrgType(
					OrgTypeEnum.getOrgType(parentOrgType)).name());
		}
		AdmOrg persist = admOrgRepo.save(org);
		if(persist.getCompany() != null){
			persist.setCompanyId(persist.getCompany().getId());
			return admOrgRepo.save(persist);
		}else{
			return persist;
		}
	}

	@Override
	public AdmOrg get(Long id) {
		if (id != null) {
			return admOrgRepo.findOne(id);
		} else {
			return null;
		}
	}

	@Override
	@Transactional
	public void delete(Long id) {
		if (id != null) {
			genericDao.executeSql(deleteOrg.toString(), new Object[] { id });
		}
	}

	@Override
	public List<Map<String, Object>> getOrgForTree(Long orgId) {
		if (orgId == null || orgId == 0) {
			List<AdmOrg> roots = admOrgRepo.findByParentIdAndFlag(null,true);
			if (roots != null && roots.size() > 0) {
				orgId = roots.get(0).getId();
			} else {
				return null;
			}
		}
		return genericDao.queryBySqlToMap(orgTreeSql.toString(),
				new Object[] { orgId });
	}

	@Override
	public Page search(AdmOrgSearchCondition cond, PageRequest pr) {
		CustomUserDetails user = StaticMethod.getUser();
		Page page = new Page();
		StringBuilder hql = new StringBuilder();
		Map<String, Object> param = new HashMap<String, Object>();
		hql.append(QUERY_ALL_VALID_ORG);
		if (cond != null) {
			if (!StringUtils.isEmpty(cond.getName())) {
				hql.append(" and o.name like :name ");
				param.put("name",SqlUtil.wrapperLike(cond.getName()));
			}
			if (!StringUtils.isEmpty(cond.getOrgType())) {
				hql.append(" and o.orgnizeType = :orgType ");
				param.put("orgType", cond.getOrgType());
			}
			
			if(user.getOrg() != null && !Constants.ORG_GROUP.equals(user.getOrg().getOrgnizeType())){
				hql.append(" and  o.companyId = :companyId ");
				param.put("companyId", user.getOrg().getCompanyId());
			}

		}

		Long count = genericDao.countByJpql(hql.toString(), param);
		List result = genericDao.queryByJpql(hql.toString(), param, pr);
		page.setTotalCount(count);
		page.setResult(result);
		return page;
	}

	@Override
	public AdmOrg getById(Long orgId) {
		return admOrgRepo.findOne(orgId);
	}

	@Override
	public int checkOrgCode(String orgCode, Long id, Long pid) {
		StringBuilder sb = new StringBuilder();
		sb.append(checkOrgCodeSql);
		if (pid != null && pid != 0) {
			boolean isCompany = false; //当前操作节点是公司
			boolean isGroup = false; 	//当前操作节点是集团
			boolean companyOper = false; //实际操作是否为公司
			List<Object> params = new ArrayList<Object>();
			AdmOrg org = admOrgRepo.findOne(pid);
			if (Constants.ORG_COMPANY.equals(org.getOrgnizeType())) {//是对公司操作
				isCompany = true;
			}
			if ( Constants.ORG_GROUP.equals(org.getOrgnizeType())) {//是对集团操作
				isGroup = true;
			}

			if (id != null) {// 如果id不空null,表示对树节点修改,此时id和pid值相同, 需获取其父节点id
				sb.append(" and id <> ").append(id);
				if(isCompany){
					companyOper = true;
					org = org.getParent() == null ? org : org.getParent(); // 获取集团节点
					sb.append(" and parent_id = ").append(org.getId());
				}else{
					// 获取组织所在的公司
					org = org.getCompany();
				}
			}else{
				if(isGroup){
					companyOper = true;
					sb.append(" and parent_id = ").append(org.getId());
				}else{
					// 获取组织所在的公司
					org = org.getCompany();
				}
			}
			
			params.add(org.getId());
			params.add(orgCode);
			Long count = genericDao.countBySql(sb.toString(), params.toArray());
			if (count > 0) {
				if(companyOper){
					return AdmOrgService.EXIST_ORG_CODE_COMPANY;
				}else{
					return AdmOrgService.EXIST_ORG_CODE_DEPARTMENT;
				}
			}
		}
		return AdmOrgService.VALID_ORG;
	}

	@Override
	public int checkOrgName(String orgName, Long id, Long pid) {
		StringBuilder sb = new StringBuilder();
		sb.append(checkOrgNameSql);
		if (pid != null && pid != 0) {
			boolean isCompany = false; //当前操作节点是公司
			boolean isGroup = false; 	//当前操作节点是集团
			boolean companyOper = false; //实际操作是否为公司
			List<Object> params = new ArrayList<Object>();
			AdmOrg org = admOrgRepo.findOne(pid); //显示当前操作节点
			if (Constants.ORG_COMPANY.equals(org.getOrgnizeType())) {//是对公司操作
				isCompany = true;
			}
			if ( Constants.ORG_GROUP.equals(org.getOrgnizeType())) {//是对集团操作
				isGroup = true;
			}
			

			if (id != null) {// 如果id不空null,表示对树节点修改,此时id和pid值相同, 需获取其父节点id
				sb.append(" and id <> ").append(id);
				if(isCompany){
					companyOper = true;
					org = org.getParent() == null ? org : org.getParent(); // 获取集团节点
					sb.append(" and parent_id = ").append(org.getId());
				}else{
					// 获取组织所在的公司
					org = org.getCompany();
				}
			}else{
				if (isGroup) {
					companyOper = true;
					sb.append(" and parent_id = ").append(org.getId());
				}else{
					// 获取组织所在的公司
					org = org.getCompany();
				}
			}

			params.add(org.getId());
			params.add(orgName);
			Long count = genericDao.countBySql(sb.toString(), params.toArray());
			if (count > 0) {
				if(companyOper){
					return AdmOrgService.EXIST_ORG_NAME_COMPANY;
				}else{
					return AdmOrgService.EXIST_ORG_NAME_DEPARTMENT;
				}
			}
		}

		return AdmOrgService.VALID_ORG;
	}

	// 查询有效组织信息HQL
	private static final String QUERY_ALL_VALID_ORG = " select o from AdmOrg o where o.flag <> 0 ";

	/**
	 * 检查组织名称在指定的公司是否唯一
	 */
	public static StringBuilder checkOrgNameSql = new StringBuilder();
	/**
	 * 检查组织编码在指定的公司是否唯一
	 */
	public static StringBuilder checkOrgCodeSql = new StringBuilder();
	/**
	 * 查询组织结构的树形结构数据
	 */
	public static StringBuilder orgTreeSql = new StringBuilder();
	/**
	 * 标记删除组织
	 */
	public static StringBuilder deleteOrg = new StringBuilder();
	static {
		orgTreeSql.append("SELECT ");
		orgTreeSql.append("t1.id ").append(ExtTreeModel.ID);
		orgTreeSql.append(",t1.parent_id ").append(ExtTreeModel.PARENT_ID);
		orgTreeSql.append(",t1.name ").append(ExtTreeModel.NAME);
		orgTreeSql.append(", t2.id ").append(ExtTreeModel.HAS_CHILDREN);
		orgTreeSql.append(", t1.code ");
		orgTreeSql.append(", t1.org_type orgType");
		orgTreeSql.append(" FROM ");
		orgTreeSql.append("( ");
		orgTreeSql.append("	SELECT * FROM adm_org ");
		orgTreeSql.append("	WHERE ");
		orgTreeSql.append("	FIND_IN_SET(id, getChildLst(?))  and flag = 1 ");
		orgTreeSql.append(") t1 ");
		orgTreeSql.append("LEFT JOIN adm_org t2 ON t1.id = t2.id ");
		orgTreeSql.append("AND EXISTS ( ");
		orgTreeSql.append("SELECT ");
		orgTreeSql.append("* ");
		orgTreeSql.append("FROM ");
		orgTreeSql.append("adm_org t3 ");
		orgTreeSql.append("WHERE ");
		orgTreeSql.append("t3.parent_id = t2.id and  t3.flag = 1 ");
		orgTreeSql.append(") order by t1.parent_id , t1.sort, t1.name ");

		deleteOrg
				.append(" update adm_org set flag = 0 where id in ( select * from ( ");
		deleteOrg
				.append(" SELECT id FROM  adm_org WHERE FIND_IN_SET(id, getChildLst(?))) t )  ");

		checkOrgCodeSql
				.append("select * from adm_org where FIND_IN_SET(id, getChildLst(?)) and `code`= ? and flag=1 ");

		checkOrgNameSql
				.append("select * from adm_org where FIND_IN_SET(id, getChildLst(?)) and `name` = ? and flag=1 ");

	}
	
	@Override
	public List<AdmOrg> queryUserOperationOrg(String orgType, String[] subTypes) {
		List<AdmOrg> orglist = null;
		
		AdmOrg userOrg = StaticMethod.getUser().getOrg();
		if(userOrg != null){
			String userOrgType = userOrg.getOrgnizeType();
			if (Constants.ORG_COMPANY.equalsIgnoreCase(orgType)) {
				if (Constants.ORG_GROUP.equalsIgnoreCase(userOrgType)) {
					orglist = admOrgRepo.findByParentIdAndFlag(userOrg.getId(),
							true);
				} else if (Constants.ORG_COMPANY.equalsIgnoreCase(userOrgType)) {
					orglist = new ArrayList<AdmOrg>();
					orglist.add(userOrg);
				} else {
					orglist = new ArrayList<AdmOrg>();
					orglist.add(userOrg.getCompany());
				}
			} else if (Constants.ORG_DEPARTMENT.equalsIgnoreCase(orgType)
					&& subTypes != null && subTypes.length > 0) {
				AdmOrg operCompany = StaticMethod.getOperationCompany();
				if (operCompany != null) {
					orglist = admOrgRepo.findByCompanyDepartmentType(
							operCompany.getId(), Arrays.asList(subTypes));
				}
			}
		}
		return orglist;
	}

	@Override
	public AdmOrg getDefaultCompany() {
		List<AdmOrg> orglist = null;
		AdmOrg group = admOrgRepo.findByCodeAndFlag("BYB", true);
		if (group != null) {
			orglist = admOrgRepo.findByParentIdAndFlag(group.getId(), true);
			return orglist == null ? null : orglist.get(0);
		}
		return null;
	}

}

/**
 * 组织类型 group: 集团 company: 公司 departenty: 部门
 */
enum OrgTypeEnum {
	GROUP, COMPANY, DEPARTMENT;

	/**
	 * 根据父组织类型获取子组织类型
	 * 
	 * @param parentOrgType
	 *            父组织类型
	 * @return
	 */
	public static OrgTypeEnum getSubOrgType(OrgTypeEnum parentOrgType) {
		switch (parentOrgType) {
		case GROUP:
			return COMPANY;
		case COMPANY:
			return DEPARTMENT;
		case DEPARTMENT:
			return DEPARTMENT;
		}

		return GROUP;
	}

	/**
	 * 根据父组织类型获取子组织类型
	 * 
	 * @param parentOrgTypeDesc
	 *            父组织类型
	 * @return
	 */
	public static OrgTypeEnum getSubOrgType(String parentOrgTypeDesc) {
		if (GROUP.name().equals(parentOrgTypeDesc)) {
			return COMPANY;
		} else if (COMPANY.name().equals(parentOrgTypeDesc)) {
			return DEPARTMENT;
		} else if (DEPARTMENT.name().equals(parentOrgTypeDesc)) {
			return DEPARTMENT;
		} else {
			return GROUP;
		}
	}

	/**
	 * 根据组织描述型获取组织类型
	 * 
	 * @param orgTypeDesc
	 *            父组织类型
	 * @return
	 */
	public static OrgTypeEnum getOrgType(String orgTypeDesc) {
		if (GROUP.name().equals(orgTypeDesc)) {
			return GROUP;
		} else if (COMPANY.name().equals(orgTypeDesc)) {
			return COMPANY;
		} else if (DEPARTMENT.name().equals(orgTypeDesc)) {
			return DEPARTMENT;
		} else {
			return GROUP;
		}
	}

}
